<?php
namespace app\controller;

use app\BaseController;
use app\common\TokenAuth;
use think\facade\Db;
use think\facade\Request;

class MakeupController extends BaseController
{
    /**
     * 获取补卡次数限制配置
     */
    public function getMakeupConfig()
    {
        $user = TokenAuth::getUserByToken();
        if (!$user) {
            return json(['code' => 401, 'msg' => '未登录或token已过期']);
        }

        try {
            // 从 checkin_setting 表获取正确的补卡限制配置
            $config = Db::name('checkin_setting')
                ->where('status', 1)
                ->order('id', 'desc')
                ->find();
            
            $makeupLimit = $config['makeup_limit'] ?? 3;
            
            return json([
                'code' => 200,
                'msg' => '获取成功',
                'data' => [
                    'makeup_limit' => $makeupLimit
                ]
            ]);
        } catch (\Exception $e) {
            trace('获取配置失败: ' . $e->getMessage(), 'error');
            return json(['code' => 500, 'msg' => '获取配置失败']);
        }
    }

    /**
     * 获取当月已使用补卡次数（详细信息）
     */
    public function getCurrentMonthUsageDetail()
    {
        $user = TokenAuth::getUserByToken();
        if (!$user) {
            return json(['code' => 401, 'msg' => '未登录或token已过期']);
        }

        try {
            $currentMonth = date('Y-m');
            
            // 获取补卡限制配置
            $config = Db::name('checkin_setting')
                ->where('status', 1)
                ->order('id', 'desc')
                ->find();
            
            $makeupLimit = $config['makeup_limit'] ?? 3;
            
            // 获取当月所有补卡申请
            $applications = Db::name('makeup_application')
                ->where('user_id', $user['id'])
                ->where('check_date', 'like', $currentMonth . '%')
                ->select()
                ->toArray();
            
            // 分类统计
            $pendingCount = 0; // 待审批
            $approvedCount = 0; // 已通过
            $rejectedCount = 0; // 已拒绝
            $totalCount = 0; // 已用次数（待审批+已通过）
            
            foreach ($applications as $app) {
                switch ($app['status']) {
                    case 1:
                        $pendingCount++;
                        $totalCount++;
                        break;
                    case 2:
                        $approvedCount++;
                        $totalCount++;
                        break;
                    case 3:
                        $rejectedCount++;
                        break;
                }
            }

            return json([
                'code' => 200,
                'msg' => '获取成功',
                'data' => [
                    'current_month' => $currentMonth,
                    'makeup_limit' => $makeupLimit,
                    'used_count' => $totalCount,
                    'remaining_count' => max(0, $makeupLimit - $totalCount),
                    'pending_count' => $pendingCount,
                    'approved_count' => $approvedCount,
                    'rejected_count' => $rejectedCount,
                    'applications' => $applications,
                    'config_source' => 'checkin_setting 表',
                    'data_source' => 'makeup_application 表'
                ]
            ]);
        } catch (\Exception $e) {
            trace('获取使用次数详情失败: ' . $e->getMessage(), 'error');
            return json(['code' => 500, 'msg' => '获取使用次数详情失败: ' . $e->getMessage()]);
        }
    }

    /**
     * 获取当月已使用补卡次数
     */
    public function getCurrentMonthUsage()
    {
        $user = TokenAuth::getUserByToken();
        if (!$user) {
            return json(['code' => 401, 'msg' => '未登录或token已过期']);
        }

        try {
            $currentMonth = date('Y-m');
            $usedCount = Db::name('makeup_application')
                ->where('user_id', $user['id'])
                ->where('check_date', 'like', $currentMonth . '%')
                ->where('status', 'in', [1, 2]) // 待审批和已通过
                ->count();

            return json([
                'code' => 200,
                'msg' => '获取成功',
                'data' => [
                    'used_count' => $usedCount
                ]
            ]);
        } catch (\Exception $e) {
            trace('获取使用次数失败: ' . $e->getMessage(), 'error');
            return json(['code' => 500, 'msg' => '获取使用次数失败']);
        }
    }

    /**
     * 获取当月异常考勤记录
     */
    public function getMonthlyAbnormalRecords()
    {
        $user = TokenAuth::getUserByToken();
        if (!$user) {
            return json(['code' => 401, 'msg' => '未登录或token已过期']);
        }

        try {
            $currentMonth = date('Y-m');
            $year = date('Y');
            $month = date('m');
            $daysInMonth = date('t');

            // 获取考勤设置
            $setting = Db::name('checkin_setting')
                ->where('status', 1)
                ->order('id', 'desc')
                ->find();

            if (!$setting) {
                return json(['code' => 400, 'msg' => '未配置考勤设置']);
            }

            // 获叕当月所有考勤记录
            $records = Db::name('attendance_record')
                ->where('user_id', $user['id'])
                ->where('check_date', 'like', $currentMonth . '%')
                ->select()
                ->toArray();

            $recordsByDate = [];
            foreach ($records as $record) {
                $recordsByDate[$record['check_date']] = $record;
            }

            $abnormalRecords = [];
            
            // 获取当前日期和时间
            $currentDate = date('Y-m-d');
            $currentTime = date('H:i:s');
            
            // 检查每一天
            for ($day = 1; $day <= $daysInMonth; $day++) {
                $date = sprintf('%s-%02d', $currentMonth, $day);
                
                // 跳过未来日期
                if ($date > $currentDate) {
                    continue;
                }

                if (!isset($recordsByDate[$date])) {
                    // 没有记录，需要生成4个时段的异常记录
                    $workType = $setting['work_type'] ?? 2;
                    
                    // 1. 上午上班缺卡 - 检查时间是否已到
                    if ($this->shouldShowTimeSlot($date, $setting['morning_start_time'], $currentDate, $currentTime) && 
                        !$this->hasExistingApplication($user['id'], $date, 1)) {
                        $abnormalRecords[] = [
                            'id' => 'morning_in_' . $date,
                            'check_date' => $date,
                            'status' => 'absent',
                            'check_type' => 'morning_in',
                            'check_time' => '',
                            'abnormal_time' => $setting['morning_start_time'],
                            'late_minutes' => 0,
                            'early_minutes' => 0,
                            'is_abnormal' => true,
                            'sort_time' => $date . ' ' . $setting['morning_start_time']
                        ];
                    }
                    
                    // 2. 上午下班缺卡（如果是两次打卡制）
                    if ($workType >= 1 && 
                        $this->shouldShowTimeSlot($date, $setting['morning_end_time'], $currentDate, $currentTime) && 
                        !$this->hasExistingApplication($user['id'], $date, 2)) {
                        $abnormalRecords[] = [
                            'id' => 'morning_out_' . $date,
                            'check_date' => $date,
                            'status' => 'absent',
                            'check_type' => 'morning_out',
                            'check_time' => '',
                            'abnormal_time' => $setting['morning_end_time'],
                            'late_minutes' => 0,
                            'early_minutes' => 0,
                            'is_abnormal' => true,
                            'sort_time' => $date . ' ' . $setting['morning_end_time']
                        ];
                    }
                    
                    // 3. 下午上班缺卡（如果是两次打卡制）
                    if ($workType == 2 && isset($setting['afternoon_start_time']) && 
                        $this->shouldShowTimeSlot($date, $setting['afternoon_start_time'], $currentDate, $currentTime) && 
                        !$this->hasExistingApplication($user['id'], $date, 3)) {
                        $abnormalRecords[] = [
                            'id' => 'afternoon_in_' . $date,
                            'check_date' => $date,
                            'status' => 'absent',
                            'check_type' => 'afternoon_in',
                            'check_time' => '',
                            'abnormal_time' => $setting['afternoon_start_time'],
                            'late_minutes' => 0,
                            'early_minutes' => 0,
                            'is_abnormal' => true,
                            'sort_time' => $date . ' ' . $setting['afternoon_start_time']
                        ];
                    }
                    
                    // 4. 下午下班缺卡（如果是两次打卡制）
                    if ($workType == 2 && isset($setting['afternoon_end_time']) && 
                        $this->shouldShowTimeSlot($date, $setting['afternoon_end_time'], $currentDate, $currentTime) && 
                        !$this->hasExistingApplication($user['id'], $date, 4)) {
                        $abnormalRecords[] = [
                            'id' => 'afternoon_out_' . $date,
                            'check_date' => $date,
                            'status' => 'absent',
                            'check_type' => 'afternoon_out',
                            'check_time' => '',
                            'abnormal_time' => $setting['afternoon_end_time'],
                            'late_minutes' => 0,
                            'early_minutes' => 0,
                            'is_abnormal' => true,
                            'sort_time' => $date . ' ' . $setting['afternoon_end_time']
                        ];
                    }
                } else {
                    $record = $recordsByDate[$date];
                    $workType = $setting['work_type'] ?? 2;
                    
                    // 检查上午上班异常（1:正常 2:迟到 3:缺卡 4:请假 5:补卡）
                    $morningInStatus = $record['morning_check_in_status'] ?? 3; // 默认为缺卡
                    if (!in_array($morningInStatus, [1, 4, 5]) && 
                        $this->shouldShowTimeSlot($date, $setting['morning_start_time'], $currentDate, $currentTime)) {
                        $hasApplication = $this->hasExistingApplication($user['id'], $date, 1);
                        if (!$hasApplication) {
                            $abnormalRecords[] = [
                                'id' => 'morning_in_' . $date,
                                'check_date' => $date,
                                'status' => $this->getStatusCode($morningInStatus),
                                'check_type' => 'morning_in',
                                'check_time' => $record['morning_check_in'] ?? '',
                                'abnormal_time' => $record['morning_check_in'] ?? $setting['morning_start_time'],
                                'late_minutes' => $this->calculateLateMinutes($record['morning_check_in'], $setting['morning_start_time']),
                                'early_minutes' => 0,
                                'is_abnormal' => true,
                                'sort_time' => $date . ' ' . ($record['morning_check_in'] ?? $setting['morning_start_time'])
                            ];
                        }
                    }
                    
                    // 检查上午下班异常（如果是两次打卡制）
                    if ($workType >= 1) {
                        $morningOutStatus = $record['morning_check_out_status'] ?? 3; // 默认为缺卡
                        if (!in_array($morningOutStatus, [1, 4, 5]) && 
                            $this->shouldShowTimeSlot($date, $setting['morning_end_time'], $currentDate, $currentTime)) {
                            $hasApplication = $this->hasExistingApplication($user['id'], $date, 2);
                            if (!$hasApplication) {
                                $abnormalRecords[] = [
                                    'id' => 'morning_out_' . $date,
                                    'check_date' => $date,
                                    'status' => $this->getStatusCode($morningOutStatus),
                                    'check_type' => 'morning_out',
                                    'check_time' => $record['morning_check_out'] ?? '',
                                    'abnormal_time' => $record['morning_check_out'] ?? $setting['morning_end_time'],
                                    'late_minutes' => 0,
                                    'early_minutes' => $this->calculateEarlyMinutes($record['morning_check_out'], $setting['morning_end_time']),
                                    'is_abnormal' => true,
                                    'sort_time' => $date . ' ' . ($record['morning_check_out'] ?? $setting['morning_end_time'])
                                ];
                            }
                        }
                    }
                    
                    // 检查下午上班异常（如果是两次打卡制）
                    if ($workType == 2 && isset($setting['afternoon_start_time'])) {
                        $afternoonInStatus = $record['afternoon_check_in_status'] ?? 3; // 默认为缺卡
                        if (!in_array($afternoonInStatus, [1, 4, 5]) && 
                            $this->shouldShowTimeSlot($date, $setting['afternoon_start_time'], $currentDate, $currentTime)) {
                            $hasApplication = $this->hasExistingApplication($user['id'], $date, 3);
                            if (!$hasApplication) {
                                $abnormalRecords[] = [
                                    'id' => 'afternoon_in_' . $date,
                                    'check_date' => $date,
                                    'status' => $this->getStatusCode($afternoonInStatus),
                                    'check_type' => 'afternoon_in',
                                    'check_time' => $record['afternoon_check_in'] ?? '',
                                    'abnormal_time' => $record['afternoon_check_in'] ?? $setting['afternoon_start_time'],
                                    'late_minutes' => $this->calculateLateMinutes($record['afternoon_check_in'], $setting['afternoon_start_time']),
                                    'early_minutes' => 0,
                                    'is_abnormal' => true,
                                    'sort_time' => $date . ' ' . ($record['afternoon_check_in'] ?? $setting['afternoon_start_time'])
                                ];
                            }
                        }
                    }
                    
                    // 检查下午下班异常
                    if ($workType == 2 && isset($setting['afternoon_end_time'])) {
                        $afternoonOutStatus = $record['afternoon_check_out_status'] ?? 3; // 默认为缺卡
                        if (!in_array($afternoonOutStatus, [1, 4, 5]) && 
                            $this->shouldShowTimeSlot($date, $setting['afternoon_end_time'], $currentDate, $currentTime)) {
                            $hasApplication = $this->hasExistingApplication($user['id'], $date, 4);
                            if (!$hasApplication) {
                                $abnormalRecords[] = [
                                    'id' => 'afternoon_out_' . $date,
                                    'check_date' => $date,
                                    'status' => $this->getStatusCode($afternoonOutStatus),
                                    'check_type' => 'afternoon_out',
                                    'check_time' => $record['afternoon_check_out'] ?? '',
                                    'abnormal_time' => $record['afternoon_check_out'] ?? $setting['afternoon_end_time'],
                                    'late_minutes' => 0,
                                    'early_minutes' => $this->calculateEarlyMinutes($record['afternoon_check_out'], $setting['afternoon_end_time']),
                                    'is_abnormal' => true,
                                    'sort_time' => $date . ' ' . ($record['afternoon_check_out'] ?? $setting['afternoon_end_time'])
                                ];
                            }
                        }
                    }
                }
            }

            // 按日期和时间倒序排列（最近的在前）
            usort($abnormalRecords, function($a, $b) {
                return strcmp($b['sort_time'], $a['sort_time']);
            });

            return json([
                'code' => 200,
                'msg' => '获取成功',
                'data' => $abnormalRecords
            ]);
        } catch (\Exception $e) {
            trace('获取异常记录失败: ' . $e->getMessage(), 'error');
            return json(['code' => 500, 'msg' => '获取异常记录失败']);
        }
    }

    /**
     * 申请补卡
     */
    public function applyMakeup()
    {
        $user = TokenAuth::getUserByToken();
        if (!$user) {
            return json(['code' => 401, 'msg' => '未登录或token已过期']);
        }

        $checkDate = Request::param('check_date');
        $checkType = Request::param('check_type', 0, 'intval');
        $checkTime = Request::param('check_time', '');
        $reason = Request::param('reason', '');

        if (empty($checkDate) || empty($reason)) {
            return json(['code' => 400, 'msg' => '参数不完整']);
        }

        try {
            // 检查是否已有申请
            $existingApp = Db::name('makeup_application')
                ->where('user_id', $user['id'])
                ->where('check_date', $checkDate)
                ->where('check_type', $checkType)
                ->where('status', 'in', [1, 2])
                ->find();

            if ($existingApp) {
                return json(['code' => 400, 'msg' => '该时段已有补卡申请，请勿重复申请']);
            }

            // 检查本月补卡次数限制
            $config = Db::name('checkin_setting')->find();
            $makeupLimit = $config['makeup_limit'] ?? 3;
            
            $currentMonth = date('Y-m');
            $usedCount = Db::name('makeup_application')
                ->where('user_id', $user['id'])
                ->where('check_date', 'like', $currentMonth . '%')
                ->where('status', 'in', [1, 2])
                ->count();

            if ($usedCount >= $makeupLimit) {
                return json(['code' => 400, 'msg' => '本月补卡次数已达上限']);
            }

            // 创建补卡申请
            $data = [
                'user_id' => $user['id'],
                'check_date' => $checkDate,
                'check_type' => $checkType,
                'check_time' => $checkTime,
                'reason' => $reason,
                'status' => 1, // 待审批
                'create_time' => date('Y-m-d H:i:s')
            ];

            $result = Db::name('makeup_application')->insert($data);

            if ($result) {
                return json(['code' => 200, 'msg' => '补卡申请提交成功']);
            } else {
                return json(['code' => 500, 'msg' => '补卡申请提交失败']);
            }
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '补卡申请提交失败']);
        }
    }

    /**
     * 检查是否已有相同类型的补卡申请
     */
    private function hasExistingApplication($userId, $checkDate, $checkType)
    {
        $application = Db::name('makeup_application')
            ->where('user_id', $userId)
            ->where('check_date', $checkDate)
            ->where('check_type', $checkType)
            ->where('status', 'in', [1, 2]) // 待审核或已通过
            ->find();
            
        return !empty($application);
    }
    
    /**
     * 获取状态码对应的文本
     */
    private function getStatusCode($statusNum)
    {
        $statusMap = [
            2 => 'late',     // 迟到
            3 => 'absent',   // 缺卡
        ];
        return $statusMap[$statusNum] ?? 'abnormal';
    }
    
    /**
     * 计算迟到分钟数
     */
    private function calculateLateMinutes($actualTime, $standardTime)
    {
        if (empty($actualTime)) {
            return 0;
        }
        
        $actual = strtotime($actualTime);
        $standard = strtotime($standardTime);
        
        if ($actual > $standard) {
            return intval(($actual - $standard) / 60);
        }
        
        return 0;
    }
    
    /**
     * 计算早退分钟数
     */
    private function calculateEarlyMinutes($actualTime, $standardTime)
    {
        if (empty($actualTime)) {
            return 0;
        }
        
        $actual = strtotime($actualTime);
        $standard = strtotime($standardTime);
        
        if ($actual < $standard) {
            return intval(($standard - $actual) / 60);
        }
        
        return 0;
    }

    /**
     * 获取考勤类型
     */
    private function getCheckType($record)
    {
        // 根据具体业务逻辑判断是上班打卡还是下班打卡
        if (!empty($record['check_in_time']) && empty($record['check_out_time'])) {
            return 1; // 上班
        } elseif (!empty($record['check_out_time'])) {
            return 2; // 下班
        }
        return 0;
    }

    /**
     * 获取打卡时间
     */
    private function getCheckTime($record)
    {
        if ($record['status'] == '迟到' && !empty($record['check_in_time'])) {
            return $record['check_in_time'];
        } elseif ($record['status'] == '早退' && !empty($record['check_out_time'])) {
            return $record['check_out_time'];
        }
        return '';
    }
    
    /**
     * 获取我的补卡申请列表
     */
    public function getMyApplications()
    {
        $user = TokenAuth::getUserByToken();
        if (!$user) {
            return json(['code' => 401, 'msg' => '未登录或token已过期']);
        }
        
        $page = Request::param('page/d', 1);
        $limit = Request::param('limit/d', 20);
        $status = Request::param('status/d');
        
        $query = Db::name('makeup_application')
            ->alias('ma')
            ->join('user u', 'ma.approver_id = u.id', 'left')
            ->where('ma.user_id', $user['id']);
        
        if (!is_null($status)) {
            $query = $query->where('ma.status', $status);
        }
        
        $total = $query->count();
        $list = $query
            ->field([
                'ma.id', 'ma.check_date', 'ma.check_type', 'ma.check_time',
                'ma.reason', 'ma.status', 'ma.approve_time', 'ma.approve_remark',
                'ma.create_time', 'u.realname as approver_name'
            ])
            ->order('ma.create_time', 'desc')
            ->page($page, $limit)
            ->select();
        
        foreach ($list as &$item) {
            $item['check_type_text'] = $this->getCheckTypeText($item['check_type']);
            $item['status_text'] = $this->getStatusText($item['status']);
        }
        
        return json([
            'code' => 200,
            'msg' => '获取成功',
            'data' => ['total' => $total, 'list' => $list]
        ]);
    }

    private function getCheckTypeText($checkType) {
        $types = [1 => '上午上班', 2 => '上午下班', 3 => '下午上班', 4 => '下午下班'];
        return $types[$checkType] ?? '未知';
    }

    private function getStatusText($status) {
        $statuses = [1 => '待审核', 2 => '已通过', 3 => '已拒绝'];
        return $statuses[$status] ?? '未知';
    }
    
    /**
     * 判断某个时间段是否应该显示（根据当前时间动态判断）
     */
    private function shouldShowTimeSlot($checkDate, $slotTime, $currentDate, $currentTime)
    {
        // 如果是历史日期，直接显示
        if ($checkDate < $currentDate) {
            return true;
        }
        
        // 如果是今天，需要判断当前时间是否已经过了该时间段
        if ($checkDate == $currentDate) {
            // 当前时间是否已经过了该时间段（给予30分钟缓冲时间）
            $slotTimestamp = strtotime($checkDate . ' ' . $slotTime);
            $currentTimestamp = strtotime($currentDate . ' ' . $currentTime);
            $bufferTime = 30 * 60; // 30分钟缓冲
            
            return $currentTimestamp >= ($slotTimestamp + $bufferTime);
        }
        
        // 未来日期不显示
        return false;
    }
}
